
<?php

/**
* 聊天室服务器  websocket 专用
*/
header("charset=utf-8");
$server_socket = new Server_socket('172.27.0.6',8888,1024);
$server_socket->start(); sleep(2);
class Server_socket
{
    private $socket;
    private $accept = [];
    private $hands = [];
    function __construct($host, $port, $max)
    {
        $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);//创建一个socket
        socket_set_option($this->socket, SOL_SOCKET, SO_REUSEADDR, TRUE);//设置协议等级
        socket_bind($this->socket, $host,$port);//绑定主机和端口
        socket_listen($this->socket,$max);//开启监听
        socket_set_nonblock($this->socket);//非阻塞
        print_r($this->socket);
    }

    public function start()
    {

        $i = 0;
        while (true) {
            $cycle = $this->accept;
            $cycle[] = $this->socket;
            socket_select($cycle, $write, $except, null);//在指定的超时套接字数组上运行select（）系统调用
            //遍历所有的socket集合
            foreach ($cycle as $sock) {
                //如果遍历到当前socket
                if ($sock == $this->socket) {
                    //接受当前套接字上的连接
                    $this->accept[] = socket_accept($sock);
                    $arr =  array_keys($this->accept);
                    $key = end($arr);
                    $this->hands[$key] = false;
                }else{
                    //从已连接的socket接收数据,长度为204800
                    $length = socket_recv($sock, $buffer, 204800, null);
                    $key = array_search($sock, $this->accept);
                    //如果查到已连接的socket为false,表示还没正式握手连接
                    if (!$this->hands[$key]) {
                        //升级握手协议
                        $this->dohandshake($sock,$buffer,$key);
                    }else if($length < 1){
                        //未读到消息
                        $this->close($sock);
                    }else{
                        //接收从客户端发送的内容 解码
                        $data = $this->decode($buffer);
//                        //组装返回的json数组
//                        $data = json_decode($data,1);
//                        $data['chat_content'] = htmlspecialchars($data['chat_content']);
//                        $data['chat_user_name'] = htmlspecialchars($data['chat_user_name']);
//                        $data['add_time'] = date('Y-m-d H:i:s',$data['add_time']);
//                        $data = json_encode($data);
//                        //服务器端的内容  编码
                        $data = $this->encode($data);
                        //将信息传递给从机
                        foreach ($this->accept as $client) {
                            socket_write($client,$data ,strlen($data));
                        }
                        $i++;
                    }
                }
            }
            // sleep(1);
        }
    }/* end of start*/

    /**
     * 首次与客户端握手
     */
    public function dohandshake($sock, $data, $key) {
        if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $data, $match)) {
            $response = base64_encode(sha1($match[1] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
            $upgrade  = "HTTP/1.1 101 Switching Protocol\r\n" .
                    "Upgrade: websocket\r\n" .
                    "Connection: Upgrade\r\n" .
                    "Sec-WebSocket-Accept: " . $response . "\r\n\r\n";
            socket_write($sock, $upgrade, strlen($upgrade));
            $this->hands[$key] = true;
        }
    }/*dohandshake*/

    /**
     * 关闭一个客户端连接
     */
    public function close($sock) {
        $key = array_search($sock, $this->accept);
        socket_close($sock);
        unset($this->accept[$key]);
        unset($this->hands[$key]);
    }

    /**
     * 字符解码
     */
    public function decode($buffer) {
        $len = $masks = $data = $decoded = null;
        $len = ord($buffer[1]) & 127;
        if ($len === 126) {
            $masks = substr($buffer, 4, 4);
            $data = substr($buffer, 8);
        }
        else if ($len === 127) {
            $masks = substr($buffer, 10, 4);
            $data = substr($buffer, 14);
        }
        else {
            $masks = substr($buffer, 2, 4);
            $data = substr($buffer, 6);
        }
        for ($index = 0; $index < strlen($data); $index++) {
            $decoded .= $data[$index] ^ $masks[$index % 4];
        }
        return $decoded;
    }

    /**
     * 字符编码
     */
    public function encode($buffer) {
        $length = strlen($buffer);
        if($length <= 125) {
            return "\x81".chr($length).$buffer;
        } else if($length <= 65535) {
            return "\x81".chr(126).pack("n", $length).$buffer;
        } else {
            return "\x81".char(127).pack("xxxxN", $length).$buffer;
        }
    }
}
?>








